<template>
  <div>
    <a-card class="card" title="仓库管理" :bordered="false">
      <repository-form ref="repository" :showSubmit="false" />
    </a-card>
    <a-card class="card" title="任务管理" :bordered="false">
      <task-form ref="task" :showSubmit="false" />
    </a-card>

    <!-- table -->
    <a-card>
      <a-table :columns="columns" :dataSource="data" :pagination="false" :loading="memberLoading">
        <template
          v-for="(col, i) in ['name', 'workId', 'department']"
          :slot="col"
          slot-scope="text, record"
        >
          <a-input
            :key="col"
            v-if="record.editable"
            style="margin: -5px 0"
            :value="text"
            :placeholder="columns[i].title"
            @change="e => handleChange(e.target.value, record.key, col)"
          />
          <template v-else>{{ text }}</template>
        </template>
        <template slot="operation" slot-scope="text, record">
          <template v-if="record.editable">
            <span v-if="record.isNew">
              <a @click="saveRow(record)">添加</a>
              <a-divider type="vertical" />
              <a-popconfirm title="是否要删除此行？" @confirm="remove(record.key)">
                <a>删除</a>
              </a-popconfirm>
            </span>
            <span v-else>
              <a @click="saveRow(record)">保存</a>
              <a-divider type="vertical" />
              <a @click="cancel(record.key)">取消</a>
            </span>
          </template>
          <span v-else>
            <a @click="toggle(record.key)">编辑</a>
            <a-divider type="vertical" />
            <a-popconfirm title="是否要删除此行？" @confirm="remove(record.key)">
              <a>删除</a>
            </a-popconfirm>
          </span>
        </template>
      </a-table>
      <a-button
        style="width: 100%; margin-top: 16px; margin-bottom: 8px"
        type="dashed"
        icon="plus"
        @click="newMember"
      >新增成员</a-button>
    </a-card>

    <!-- fixed footer toolbar -->
    <footer-tool-bar
      :style="{ width: isSideMenu() && isDesktop() ? `calc(100% - ${sidebarOpened ? 256 : 80}px)` : '100%'}"
    >
      <span class="popover-wrapper">
        <a-popover
          title="表单校验信息"
          overlayClassName="antd-pro-pages-forms-style-errorPopover"
          trigger="click"
          :getPopupContainer="trigger => trigger.parentNode"
        >
          <template slot="content">
            <li
              v-for="item in errors"
              :key="item.key"
              @click="scrollToField(item.key)"
              class="antd-pro-pages-forms-style-errorListItem"
            >
              <a-icon type="cross-circle-o" class="antd-pro-pages-forms-style-errorIcon" />
              <div class>{{ item.message }}</div>
              <div class="antd-pro-pages-forms-style-errorField">{{ item.fieldLabel }}</div>
            </li>
          </template>
          <span class="antd-pro-pages-forms-style-errorIcon" v-if="errors.length > 0">
            <a-icon type="exclamation-circle" />
            {{ errors.length }}
          </span>
        </a-popover>
      </span>
      <a-button type="primary" @click="validate" :loading="loading">提交</a-button>
    </footer-tool-bar>
  </div>
</template>

<script>
import RepositoryForm from './RepositoryForm'
import TaskForm from './TaskForm'
import FooterToolBar from '@/components/FooterToolbar'
import { mixin, mixinDevice } from '@/utils/mixin'

const fieldLabels = {
    name: '仓库名',
    url: '仓库域名',
    owner: '仓库管理员',
    approver: '审批人',
    dateRange: '生效日期',
    type: '仓库类型',
    name2: '任务名',
    url2: '任务描述',
    owner2: '执行人',
    approver2: '责任人',
    dateRange2: '生效日期',
    type2: '任务类型'
}

export default {
    name: 'AdvancedForm',
    mixins: [mixin, mixinDevice],
    components: {
        FooterToolBar,
        RepositoryForm,
        TaskForm
    },
    data() {
        return {
            description: '高级表单常见于一次性输入和提交大批量数据的场景。',
            loading: false,
            memberLoading: false,

            // table
            columns: [
                {
                    title: '成员姓名',
                    dataIndex: 'name',
                    key: 'name',
                    width: '20%',
                    scopedSlots: { customRender: 'name' }
                },
                {
                    title: '工号',
                    dataIndex: 'workId',
                    key: 'workId',
                    width: '20%',
                    scopedSlots: { customRender: 'workId' }
                },
                {
                    title: '所属部门',
                    dataIndex: 'department',
                    key: 'department',
                    width: '40%',
                    scopedSlots: { customRender: 'department' }
                },
                {
                    title: '操作',
                    key: 'action',
                    scopedSlots: { customRender: 'operation' }
                }
            ],
            data: [
                {
                    key: '1',
                    name: '小明',
                    workId: '001',
                    editable: false,
                    department: '行政部'
                },
                {
                    key: '2',
                    name: '李莉',
                    workId: '002',
                    editable: false,
                    department: 'IT部'
                },
                {
                    key: '3',
                    name: '王小帅',
                    workId: '003',
                    editable: false,
                    department: '财务部'
                }
            ],

            errors: []
        }
    },
    methods: {
        handleSubmit(e) {
            e.preventDefault()
        },
        newMember() {
            const length = this.data.length
            this.data.push({
                key: length === 0 ? '1' : (parseInt(this.data[length - 1].key) + 1).toString(),
                name: '',
                workId: '',
                department: '',
                editable: true,
                isNew: true
            })
        },
        remove(key) {
            const newData = this.data.filter(item => item.key !== key)
            this.data = newData
        },
        saveRow(record) {
            this.memberLoading = true
            const { key, name, workId, department } = record
            if (!name || !workId || !department) {
                this.memberLoading = false
                this.$message.error('请填写完整成员信息。')
                return
            }
            // 模拟网络请求、卡顿 800ms
            new Promise(resolve => {
                setTimeout(() => {
                    resolve({ loop: false })
                }, 800)
            }).then(() => {
                const target = this.data.find(item => item.key === key)
                target.editable = false
                target.isNew = false
                this.memberLoading = false
            })
        },
        toggle(key) {
            const target = this.data.find(item => item.key === key)
            target._originalData = { ...target }
            target.editable = !target.editable
        },
        getRowByKey(key, newData) {
            const data = this.data
            return (newData || data).find(item => item.key === key)
        },
        cancel(key) {
            const target = this.data.find(item => item.key === key)
            Object.keys(target).forEach(key => {
                target[key] = target._originalData[key]
            })
            target._originalData = undefined
        },
        handleChange(value, key, column) {
            const newData = [...this.data]
            const target = newData.find(item => key === item.key)
            if (target) {
                target[column] = value
                this.data = newData
            }
        },

        // 最终全页面提交
        validate() {
            const {
                $refs: { repository, task },
                $notification
            } = this
            const repositoryForm = new Promise((resolve, reject) => {
                repository.form.validateFields((err, values) => {
                    if (err) {
                        reject(err)
                        return
                    }
                    resolve(values)
                })
            })
            const taskForm = new Promise((resolve, reject) => {
                task.form.validateFields((err, values) => {
                    if (err) {
                        reject(err)
                        return
                    }
                    resolve(values)
                })
            })

            // clean this.errors
            this.errors = []
            Promise.all([repositoryForm, taskForm])
                .then(values => {
                    $notification['error']({
                        message: 'Received values of form:',
                        description: JSON.stringify(values)
                    })
                })
                .catch(() => {
                    const errors = Object.assign({}, repository.form.getFieldsError(), task.form.getFieldsError())
                    const tmp = { ...errors }
                    this.errorList(tmp)
                })
        },
        errorList(errors) {
            if (!errors || errors.length === 0) {
                return
            }
            this.errors = Object.keys(errors)
                .filter(key => errors[key])
                .map(key => ({
                    key: key,
                    message: errors[key][0],
                    fieldLabel: fieldLabels[key]
                }))
        },
        scrollToField(fieldKey) {
            const labelNode = document.querySelector(`label[for="${fieldKey}"]`)
            if (labelNode) {
                labelNode.scrollIntoView(true)
            }
        }
    }
}
</script>

<style lang="less" scoped>
.card {
    margin-bottom: 24px;
}
.popover-wrapper {
    /deep/ .antd-pro-pages-forms-style-errorPopover .ant-popover-inner-content {
        min-width: 256px;
        max-height: 290px;
        padding: 0;
        overflow: auto;
    }
}
.antd-pro-pages-forms-style-errorIcon {
    user-select: none;
    margin-right: 24px;
    color: #f5222d;
    cursor: pointer;
    i {
        margin-right: 4px;
    }
}
.antd-pro-pages-forms-style-errorListItem {
    padding: 8px 16px;
    list-style: none;
    border-bottom: 1px solid #e8e8e8;
    cursor: pointer;
    transition: all 0.3s;

    &:hover {
        background: #e6f7ff;
    }
    .antd-pro-pages-forms-style-errorIcon {
        float: left;
        margin-top: 4px;
        margin-right: 12px;
        padding-bottom: 22px;
        color: #f5222d;
    }
    .antd-pro-pages-forms-style-errorField {
        margin-top: 2px;
        color: rgba(0, 0, 0, 0.45);
        font-size: 12px;
    }
}
</style>
